package com.ruicar.afs.jobadmin.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.jobadmin.core.conf.JobAdminConfig;
import com.ruicar.afs.jobadmin.core.cron.CronExpression;
import com.ruicar.afs.jobadmin.core.model.AfsJobGroup;
import com.ruicar.afs.jobadmin.core.model.AfsJobInfo;
import com.ruicar.afs.jobadmin.core.thread.JobTriggerPoolHelper;
import com.ruicar.afs.jobadmin.core.trigger.TriggerTypeEnum;
import com.ruicar.afs.jobadmin.core.util.I18nUtil;
import com.ruicar.afs.jobadmin.mapper.AfsJobGroupMapper;
import com.ruicar.afs.jobadmin.mapper.AfsJobInfoMapper;
import com.ruicar.afs.jobadmin.service.AfsJobService;
import com.ruicar.afs.cloud.common.job.core.util.DateUtil;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * The type JobInfoController
 * <p>Description: </p>
 *
 * @author Fzero
 * @version 1.0
 * @date Created on 2020.06.13 14:17:13
 * @since 1.0
 */
@RestController
@RequestMapping("/jobinfo")
@AllArgsConstructor
public class JobInfoController {

    /**
     * Afs job group mapper
     * <p>Description: </p>
     */
    private AfsJobGroupMapper afsJobGroupMapper;
    /**
     * Afs job info mapper
     * <p>Description: </p>
     */
    private AfsJobInfoMapper afsJobInfoMapper;
    /**
     * Afs job service
     * <p>Description: </p>
     */
    private AfsJobService afsJobService;


    /**
     * Page list response
     *
     * @param pageNum         page num
     * @param pageSize        page size
     * @param jobGroup        job group
     * @param triggerStatus   trigger status
     * @param jobDesc         job desc
     * @param executorHandler executor handler
     * @return the response
     */
    @RequestMapping("/pageList")
    @ResponseBody
    public IResponse<Map<String, Object>> pageList(
            @RequestParam(required = false, defaultValue = "1") int pageNum,
            @RequestParam(required = false, defaultValue = "10") int pageSize,
            @RequestParam(required = false,defaultValue = "-1") int jobGroup,
            @RequestParam(required = false ,defaultValue = "-1") int triggerStatus,
            @RequestParam(required = false) String jobDesc,
            @RequestParam(required = false) String executorHandler) {

        return IResponse.success(afsJobInfoMapper.selectPage(new Page(pageNum,pageSize),
                Wrappers.<AfsJobInfo>lambdaQuery()
                        .eq(jobGroup>0, AfsJobInfo::getJobGroup,jobGroup)
                        .eq(triggerStatus>0, AfsJobInfo::getTriggerStatus,triggerStatus)
                        .like(StringUtils.isNotEmpty(jobDesc), AfsJobInfo::getJobDesc,jobDesc)
                        .like(StringUtils.isNotEmpty(executorHandler), AfsJobInfo::getExecutorHandler,executorHandler)

            )
        );
    }

    /**
     * Add response
     *
     * @param jobInfo job info
     * @return the response
     */
    @PostMapping("/add")
    public IResponse<String> add(@RequestBody AfsJobInfo jobInfo) {
        return afsJobService.add(jobInfo);
    }

    /**
     * Update response
     *
     * @param jobInfo job info
     * @return the response
     */
    @PostMapping("/update")
    public IResponse<String> update(@RequestBody AfsJobInfo jobInfo) {
        return afsJobService.update(jobInfo);
    }

    /**
     * Remove response
     *
     * @param id id
     * @return the response
     */
    @GetMapping("/remove")
    public IResponse<Boolean> remove(int id) {
        return afsJobService.remove(id);
    }

    /**
     * Pause response
     *
     * @param id id
     * @return the response
     */
    @GetMapping("/stop")
    public IResponse<String> pause(int id) {
        return afsJobService.stop(id);
    }

    /**
     * Start response
     *
     * @param id id
     * @return the response
     */
    @GetMapping("/start")
    public IResponse<String> start(int id) {
        return afsJobService.start(id);
    }

    /**
     * Trigger job response
     *
     * @param id            id
     * @param param executor param
     * @return the response
     */
    @GetMapping("/trigger")
    public IResponse<String> triggerJob(int id,String address, String param) {
        // force cover job param
        if (param == null) {
            param = "";
        }
        if(StringUtils.isEmpty(address)) {
            JobTriggerPoolHelper.trigger(id, TriggerTypeEnum.MANUAL, -1, null, param);
        }else{
            AfsJobInfo jobInfo = JobAdminConfig.getAdminConfig().getAfsJobInfoMapper().loadById(id);
            AfsJobGroup group = JobAdminConfig.getAdminConfig().getAfsJobGroupMapper().load(jobInfo.getJobGroup());
            Assert.isTrue(StringUtils.isNotEmpty(group.getAddressList()),address+"未注册");
            Assert.isTrue(group.getAddressList().indexOf(address)>-1,address+"未注册");
            JobTriggerPoolHelper.triggerWithAddress(id, TriggerTypeEnum.MANUAL, -1, param,address);
        }
        return IResponse.success("");
    }

    /**
     * Next trigger time response
     *
     * @param cron cron
     * @return the response
     */
    @RequestMapping("/nextTriggerTime")
    @ResponseBody
    public IResponse<List<String>> nextTriggerTime(String cron) {
        List<String> result = new ArrayList<>();
        try {
            CronExpression cronExpression = new CronExpression(cron);
            Date lastTime = new Date();
            for (int i = 0; i < 5; i++) {
                lastTime = cronExpression.getNextValidTimeAfter(lastTime);
                if (lastTime != null) {
                    result.add(DateUtil.formatDateTime(lastTime));
                } else {
                    break;
                }
            }
        } catch (ParseException e) {
            return IResponse.fail(I18nUtil.getString("jobinfo_field_cron_unvalid"));
        }
        return IResponse.success(result);
    }

    /**
     * Get jobs by group response
     *
     * @param jobGroup job group
     * @return the response
     */
    @PostMapping("/getJobsByGroup")
    public IResponse<List<AfsJobInfo>> getJobsByGroup(int jobGroup) {
        return IResponse.success(afsJobInfoMapper.getJobsByGroup(jobGroup));
    }

}
